package it.gius.pe.shapes;

import it.gius.pe.aabb.AABoundaryBox;
import it.gius.pe.shapes.witness.PolyPointWitness;
import it.gius.pe.shapes.witness.Witness;

import org.jbox2d.common.Vec2;

public class Polygon extends Shape{

	private Vec2[] vertices;
	private int verticesNum;
	private static int defaultArraySize = 10;
	private int arrayMult = 1;

	private boolean done = false;

	public Vec2 center;
	
	public Vec2 velocity = new Vec2();

	public Polygon() {
		vertices = new Vec2[defaultArraySize*arrayMult];
		verticesNum = 0;
		velocity.setZero();
	}


	public void reset()
	{
		done = false;
		verticesNum = 0;
		velocity.setZero();
	}
	
	/*public void setVelocity(Vec2 velocity)
	{
		if(velocity != null)
			this.velocity = velocity;
	}*/
	
	@Override
	public void  fromWitnessToVec(Witness witness, Vec2 result) {
		
		/*if(witness == null)
		{
			result.set(vertices[0]);
			return;
		}*/
		
		PolyPointWitness pwit = (PolyPointWitness)witness;
		
		if(witness != null && pwit.index >=0 && pwit.index < verticesNum)
			result.set(vertices[pwit.index]);
		else
			throw new IllegalArgumentException();
		
	}

	private void resizeArray()
	{
		if(verticesNum < vertices.length)
			return;

		arrayMult++;
		Vec2[] newArray = new Vec2[defaultArraySize*arrayMult];
		for(int i=0; i < verticesNum; i++)
		{
			newArray[i] = vertices[i];
		}
		vertices = newArray;
	}
	
	public void setPosition(Vec2 newCenter)
	{
		if(!done)
			return;
		
		Vec2 oldV1 = vertices[0];
		Vec2 vc = oldV1.sub(this.center);
		
		this.center.set(newCenter);
		
		vertices[0] = center.add(vc);
		
		Vec2 d = vertices[0].sub(oldV1);
		
		for(int i=1; i<verticesNum; i++)
			vertices[i].addLocal(d);
		
		
	}


	public boolean addVertex(Vec2 p)
	{
		if(!done)
		{
			vertices[verticesNum] = p;
			verticesNum++;
			resizeArray();
			return true;
		}
		
		return false;
	}
	
	public int getVerticesCount()
	{
		return verticesNum;
	}
	
	public Vec2 getVertex(int index)
	{
		return vertices[index];//.clone();
	}

	public void endPolygon() throws BadShapeException
	{
		if(!isValid())
			throw new BadShapeException();

		center = new Vec2();
		center.setZero();
		for(int i=0; i < verticesNum;i++)
		{
			center.addLocal(vertices[i]);
		}
		center.mulLocal(1/(float)verticesNum);

		done= true;
	}

	public boolean isValid()
	{
		
		if(done)
			return true;

		if(verticesNum <=2)
			return false;

		float oldSign = 0;
		for(int i = 0; i < verticesNum; i++)
		{
			int i1 = i;
			int i2 = (i+1) % verticesNum;
			int i3 = (i+2) % verticesNum;
			Vec2 v1 = vertices[i1];			
			Vec2 v2 = vertices[i2];
			Vec2 v3 = vertices[i3];

			Vec2 v12 = v2.sub(v1);

			Vec2 q = v3.sub(v2);

			float r = Vec2.cross(q, v12);

			if(i != 0)
			{
				if((r>0 && oldSign <0) ||(r<0 && oldSign>0))
					return false;
			}

			oldSign = r;
		}

		return true;
	}
	
	@Override
	public void getBoundaryBox(AABoundaryBox result) throws BadShapeException
	{
		if(!done)
			throw new BadShapeException();
		
		//Vec2 lowerBound = new Vec2();
		//Vec2 upperBound = new Vec2();
		result.lowerBound.set(vertices[0]);
		result.upperBound.set(vertices[0]);
		
		for(int i=0; i < verticesNum; i++)
		{
			if(vertices[i].x < result.lowerBound.x)
				result.lowerBound.x = vertices[i].x;
			
			if(vertices[i].y < result.lowerBound.y)
				result.lowerBound.y = vertices[i].y;
			
			if(vertices[i].x > result.upperBound.x)
				result.upperBound.x = vertices[i].x;
			
			if(vertices[i].y > result.upperBound.y)
				result.upperBound.y = vertices[i].y;
		}
		
		//BoundaryBox bbox = new BoundaryBox(lowerBound,upperBound);
		
		//return bbox;
		
	}
	
	public void move()
	{
		if(!done)
			return;
		
		center.addLocal(velocity);
		
		for(int i=0; i< verticesNum; i++)
		{
			vertices[i].addLocal(velocity);
		}
	}



	/*public Vec2 getCeter() {
		return center;//.clone();
	}*/

}
